package com.zhijian.medical.aop;

import com.zhijian.medical.config.Constants;
import com.zhijian.medical.entity.dto.PersonDto;
import com.zhijian.medical.entity.po.Person;
import com.zhijian.medical.enums.PersonStatusEnum;
import com.zhijian.medical.enums.ResponseCodeEnum;
import com.zhijian.medical.exception.BusinessException;
import com.zhijian.medical.holder.CurrentUserHolder;
import com.zhijian.medical.service.CacheService;
import com.zhijian.medical.service.PersonService;
import com.zhijian.medical.util.JsonUtil;
import com.zhijian.medical.util.TokenBean;
import com.zhijian.medical.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;


/**
 * 登陆拦截
 *
 * @Author hcg
 * @Date 2022年6月2
 * @Version 1.0.1
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    private CacheService cacheService;

    private PersonService personService;

    public LoginInterceptor() {
    }

    public LoginInterceptor(CacheService cacheService, PersonService personService) {
        this.cacheService = cacheService;
        this.personService = personService;
    }

    /**
     * 拦截请求，校验token
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String token = request.getHeader(Constants.MEDICAL_TOKEN);
        if (StringUtils.isBlank(token)) {
            log.warn("【LoginInterceptor】 error,the parameter '{}' is empty", Constants.MEDICAL_TOKEN);
            log.warn("the request path is {}", request.getRequestURI());
            throw new BusinessException(ResponseCodeEnum.ERROR_AUTH_LOGIN);
        }
        //根据token获取创建时的用户信息
        PersonDto user = cacheService.getPersonDtoByToken(token);
        if (Objects.isNull(user)) {
            log.warn("【LoginInterceptor】 error,can not get user by token {}", token);
            log.warn("the request path is {}", request.getRequestURI());
            throw new BusinessException(ResponseCodeEnum.ERROR_AUTH_LOGIN);
        }
        Person u = personService.selectById(user.getId());
        if (Objects.isNull(u)) {
            //每次都查下
            log.warn("【LoginInterceptor】 error, the user is not exist, the id is {}", user.getId());
            log.warn("the request path is {}", request.getRequestURI());
            throw new BusinessException(ResponseCodeEnum.ERROR_AUTH_LOGIN);
        }
        if (u.getStatus() != PersonStatusEnum.NORMAL.getCode().byteValue()) {
            //冻结
            log.warn("【LoginInterceptor】 error, the user is frees, the id is {}", user.getId());
            log.warn("the request path is {}", request.getRequestURI());
            throw new BusinessException(ResponseCodeEnum.ERROR_AUTH_LOGIN);
        }
        //校验用户token状态
        //token版本号
        String tokenVersion = "1.0";
        TokenBean tokenBean = new TokenBean(Constants.TOKEN_ACCESS_KEY, Constants.TOKEN_SECRET_KEY, tokenVersion, "login", "POST", null, JsonUtil.toString(user));
        if (!TokenUtil.validateToken(token, tokenBean, true)) {
            log.error("【LoginInterceptor】 error,token valid false, {}", token);
            log.warn("the request path is {}", request.getRequestURI());
            throw new BusinessException(ResponseCodeEnum.ERROR_AUTH_LOGIN);
        }
        //延长时间
        cacheService.setex(String.format(Constants.Redis.USER_LOGIN_TOKEN, user.getPhone(), user.getSort()), Constants.LOGIN_EXPIRE_TIME, token);
        //缓存生成token的用户信息
        cacheService.setex(String.format(Constants.Redis.TOKEN_LOGIN_USER, token), Constants.LOGIN_EXPIRE_TIME, JsonUtil.toString(user));
        CurrentUserHolder.setUser(user);
        return true;
    }

}